package com.atguigu.crowd.mvc.config;

import com.atguigu.crowd.exception.AccessForbiddenException;
import com.atguigu.crowd.exception.LoginAcctAlreadyInUseException;
import com.atguigu.crowd.exception.LoginFailedException;
import com.atguigu.crowd.exception.UpdateAcctAlreadyExistException;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 异常处理配置类
 *
 * @author cyb315
 * @create 2021-10-18 17:38
 */
@ControllerAdvice
public class CrowdExceptionResolver {


    /**
     * 通用的异常处理方法
     *
     * @param viewName  非ajax请求时出现异常要跳转的视图名称
     * @param exception 实际捕获到的异常类型对象
     * @param request   请求对象
     * @param response  响应对象
     * @return
     * @throws IOException
     */
    public ModelAndView commonResolveException(String viewName, Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException {

        //用于判断当前请求是否是ajax请求
        boolean judgeRequestType = CrowdUtil.judgeRequestType(request);

        //如果是ajax请求
        if (judgeRequestType) {
            //创建一个ResultEntity对象封装错误信息
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());

            //创建Gson对象
            Gson gson = new Gson();

            //将resultEntity转换成json字符串
            String json = gson.toJson(resultEntity);

            //将json字符串作为响应体返回给浏览器
            response.getWriter().write(json);

            //由于已经通过原生的response对象返回了响应，这里不返回ModelAndView对象
            return null;
        }

        //如果不是ajax请求
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("exception", exception);
        modelAndView.setViewName(viewName);
        return modelAndView;
    }

    /**
     * 处理ArithmeticException异常的异常处理方法
     *
     * @param exception 实际捕获到的异常类型对象
     * @param request   当前请求对象
     * @param response  当前响应对象
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveNullArithmeticException(ArithmeticException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return commonResolveException(viewName, exception, request, response);
    }


    /**
     * 处理NullPointerException异常的异常处理方法
     *
     * @param exception 实际捕获到的异常类型对象
     * @param request   当前请求对象
     * @param response  当前响应对象
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(NullPointerException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return commonResolveException(viewName, exception, request, response);
    }

    /**
     * 处理登录失败异常LoginFailedException的异常处理方法
     *
     * @param exception 实际捕获到的异常类型对象
     * @param request   当前请求对象
     * @param response  当前响应对象
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(LoginFailedException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "admin-login";
        return commonResolveException(viewName, exception, request, response);
    }

    /**
     * 处理运行时异常
     *
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = RuntimeException.class)
    public ModelAndView resolveRuntimeException(RuntimeException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return commonResolveException(viewName, exception, request, response);
    }

    /**
     * 处理Exception
     *
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = Exception.class)
    public ModelAndView resolveException(Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return commonResolveException(viewName, exception, request, response);
    }

    /**
     * 处理自定义异常LoginAcctAlreadyInUseException
     *
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveLoginAcctAlreadyInUseException(LoginAcctAlreadyInUseException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "admin-add";
        return commonResolveException(viewName, exception, request, response);
    }

    /**
     * 处理自定义异常UpdateAcctAlreadyExistException
     *
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = UpdateAcctAlreadyExistException.class)
    public ModelAndView resolveUpdateAcctAlreadyExistException(UpdateAcctAlreadyExistException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return commonResolveException(viewName, exception, request, response);
    }



}
